﻿using Axiom.CodeManifold.Framework;
using Axiom.CodeManifold.Properties;
using EnvDTE;
using Microsoft.VisualStudio.Tools;
using System;
using System.Collections;
using System.Collections.Generic;
using System.DirectoryServices;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace Axiom.CodeManifold
{
	public class Euclid
	{
		private static EnvDTE.DTE ide = null;

		private static Euclid _instance;

		public static Euclid Instance
		{
			get
			{
				if (Euclid._instance == null)
				{
					Euclid._instance = new Euclid();
				}
				return Euclid._instance;
			}
		}

		public EnvDTE.DTE Ide
		{
			get
			{
				return ide;
			}
		}

		public static EnvDTE.DTE Host { set { ide = value; IsHosted = true; } }

		public bool IsReady
		{
			get
			{
				var result = Msdev.GetOpenIDESolutions().ContainsKey(ReferenceData.SolutionFullName);
				return result;
			}
		}

		public static bool IsHosted { get; private set; }

		public void Attach(string path)
		{
			var instances = Msdev.GetOpenIDESolutions();
			if (instances.ContainsKey(path))
			{
				ide = instances[path];
			}
			else
			{
				ide = null;
			}
		}

		public void LaunchSolutionInstances()
		{
			var instances = Msdev.GetOpenIDESolutions();
			if (!instances.ContainsKey(ReferenceData.SolutionFullName))
			{
				Msdev.ShowIDE(ReferenceData.SolutionFullName);
			}
		}

		private void IdeClosing()
		{
			ide = null;
		}

		public void SortMembers()
		{
			if (Ide == null)
			{
				throw new NoActiveIDEInstanceException("No Active IDE Instance");
			}

			Ide.ActiveDocument.SortMembers();
		}

		internal void DoSomeTest()
		{
			GetProjects();
		}

		public string SolutionFullName
		{
			get
			{
				if (ide == null)
				{
					return "Disonnected";
				}
				else if (ide != null && !ide.Solution.IsOpen)
				{
					return "No attached solution";
				}
				else
				{
					return Ide.Solution.FullName;
				}

			}
		}

		public void AutoCommentDocument()
		{
			if (Ide == null)
			{
				throw new NoActiveIDEInstanceException("No Active IDE Instance");
			}

			Ide.ActiveDocument.AutoComment();
		}

		public static void AutoCommentAllFiles()
		{
			var codemodels = ide.ActiveDocument.GetProject().GetCodeModels();

			foreach (FileCodeModel model in codemodels)
			{
				ProjectItem item = model.Parent as ProjectItem;

				if (Path.GetExtension(item.FileNames[0]) != ".cs" || item.FileNames[0].EndsWith(".designer.cs", StringComparison.CurrentCultureIgnoreCase))
				{
					continue;
				}

				item.Open().Activate();
				ide.ActiveDocument.AutoComment();
			}
		}

		public void OpenUndo()
		{
			if (ide.UndoContext.IsOpen)
			{
				ide.UndoContext.Close();
			}

			if (ReferenceData.UseUndoContext)
			{
				ide.UndoContext.Open("test-context");
			}
		}

		public void Undo()
		{
			if (ide.UndoContext.IsOpen)
			{
				ide.UndoContext.SetAborted();
			}
		}

		public IEnumerable<ProjectCodeModel> GetProjects()
		{
			var results = new List<ProjectCodeModel>();

			foreach (var project in ide.AllProjects())
			{
				var proj = new ProjectCodeModel(project);
				results.Add(proj);
			}
			return results;
		}
	}
}
